/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.service.utils;

import cn.ac.nercis.pes.common.annotation.CheckField;
import cn.ac.nercis.pes.model.dto.project.ImportConflictDTO;
import com.alibaba.excel.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 字段检查辅助类
 *
 * @author zpy
 * @version 1.0.0
 */
@Slf4j
public final class CheckFieldUtils {
    private CheckFieldUtils() {
    }

    public static List<ImportConflictDTO> checkField(Object sourceObj, Object importObj) {
        if (Objects.isNull(sourceObj) || Objects.isNull(importObj)) {
            return Collections.emptyList();
        }
        try {
            List<ImportConflictDTO> importConflictDTOS = new ArrayList<>();
            for (Field field : importObj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                CheckField checkField = field.getAnnotation(CheckField.class);
                Field sourceField = getField(sourceObj.getClass(), field.getName());
                if (Objects.isNull(checkField) || Objects.isNull(sourceField)) {
                    continue;
                }
                sourceField.setAccessible(true);
                ImportConflictDTO conflictDTO = checkField(sourceObj, importObj, field, sourceField, checkField);
                if (Objects.nonNull(conflictDTO)) {
                    importConflictDTOS.add(conflictDTO);
                }
            }
            return importConflictDTOS;
        } catch (Exception ex) {
            log.error("获取字段检查内容出错：", ex);
            return Collections.emptyList();
        }
    }

    public static <T> T applyContent(T sourceContent, T importContent, Boolean cover) {
        return cover ? importContent : sourceContent;
    }

    private static Field getField(Class<?> obj, String fieldName) {
        try {
            return obj.getDeclaredField(fieldName);
        } catch (NoSuchFieldException | SecurityException ex) {
            return null;
        }
    }

    private static ImportConflictDTO checkField(Object sourceObj, Object importObj, Field importField, Field sourceField,
                                                CheckField checkField) {
        try {
            if (checkField.isBoolean()) {
                if (hasConflictByBoolean(sourceField.get(sourceObj), importField.get(importObj))) {
                    return ImportConflictDTO.builder()
                            .fieldName(checkField.name())
                            .oldContent(convertToBoolean(sourceField.get(sourceObj)) ? checkField.yesDesc() : checkField.noDesc())
                            .newContent(convertToBoolean(importField.get(importObj)) ? checkField.yesDesc() : checkField.noDesc())
                            .build();
                }
            } else {
                if (hasConflict(sourceField.get(sourceObj), importField.get(importObj))) {
                    return ImportConflictDTO.builder()
                            .fieldName(checkField.name())
                            .oldContent(String.valueOf(sourceField.get(sourceObj)))
                            .newContent(String.valueOf(importField.get(importObj)))
                            .build();
                }
            }
            return null;
        } catch (Exception ex) {
            return null;
        }
    }

    private static boolean hasConflict(Object sourceContent, Object importContent) {
        if (Objects.isNull(sourceContent) || Objects.isNull(importContent)) {
            return false;
        }
        return !StringUtils.equals(String.valueOf(sourceContent), String.valueOf(importContent));
    }

    private static boolean hasConflictByBoolean(Object sourceContent, Object importContent) {
        if (Objects.isNull(sourceContent) || Objects.isNull(importContent)) {
            return false;
        }
        return convertToBoolean(sourceContent) != convertToBoolean(importContent);
    }

    private static boolean convertToBoolean(Object content) {
        try {
            return Boolean.parseBoolean(String.valueOf(content));
        } catch (Exception ex) {
            return false;
        }
    }
}